package Factory;

import Factory.ENUM.CAL_MODE;
import Model.DrawModel.CalPoint;
import Model.DrawModel.HistoricalTrack;
import Model.SurroundModel.Ship;
import Service.ShipCalculate;
import Service.SurroundService.*;
import Service.TransformService.TransformService;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * 计算类工厂
 * @author dingN
 * @date 2022/06/22
 */
public class CalculateClassFactory {

    static ParamChangeUtil paramChangeUtil; // 参数转换器
    static ShipCalculate shipCal; // 计算实例
    /**
     * 获取计算服务
     * @param targetList          目标列表
     * @param shipsList           船舶名单
     * @param center              中心
     * @param historicalShipsList 历史船舶名单
     * @param CAL_MODE       计算模式
     * @return {@link ShipCalculate}
     */
    public static ShipCalculate getService(
            ArrayList<CalPoint> targetList,
            ArrayList<CalPoint> shipsList,
            ArrayList<CalPoint> VirtualTargetList,
            CalPoint center,
            ArrayList<HistoricalTrack> historicalShipsList,
            int sleepTime,
            CAL_MODE CAL_MODE,
            ArrayList<Ship>... Ships
    ) {
        System.out.println("调用生产函数");

        // 设置数据转换器中的绘图数据
        paramChangeUtil = new ParamChangeUtil(
                targetList,
                shipsList,
                VirtualTargetList,
                center,
                historicalShipsList
        );
        paramChangeUtil.setShipMinDis(new ArrayList<>());
        paramChangeUtil.setShipEvDis(new ArrayList<>());
        paramChangeUtil.setSurround(new ArrayList<>());

        // 生产计算实例
        ShipCalculate result;

        switch (CAL_MODE) {
            case FIRST_ORDER_MOVED:
                result = new FirstOrderMovingTargetsService(sleepTime);
                break;
            case FIRST_ORDER_STATIC:
                result = new FirstOrderStaticTargetsService(sleepTime);
                break;
            case FIRST_ORDER_ADAPTION_STATIC:
                result = new FirstOrderAdaptStaticTargetsService(sleepTime);
                break;
            case FIRST_ORDER_ADAPTION_MOVING:
                result = new FirstOrderAdaptMovingTargetsService(sleepTime);
                break;
            case INTERMITTENT_COM:
                result = new IntermittentCommunicationService(sleepTime);
                break;
            case SECOND_STATIC:
                result = new SecondOrderStaticTargetService(sleepTime);
                break;
            case TRANS:
                result = new TransformService(sleepTime, Ships[0], Ships[1]);
                break;
            case FIRST_ORDER_UN:
                result = new FirstOrderNumberRangeTargets(sleepTime);
                break;
            case FIRST_ORDER_UN_MOVING:
                result = new FirstOrderNumberRangeMovingTargets(sleepTime);
                break;
            default:
                result = null;
                break;
        }

        result.Init(); // 初始化计算组件的数据，在这里进行前置操作

        shipCal = result;

        return result;
    }

    public static void SetChartDataSource(
            List<Double> shipMinDis,
            List<Double> shipEvDis
            ) {
        paramChangeUtil.setShipEvDis(shipEvDis);
        paramChangeUtil.setShipMinDis(shipMinDis);
    }


    /**
     * 运行计算组件
     *
     * @param shipCalculate 船计算
     */
    public static void RunComputingComponent(ShipCalculate shipCalculate) {
        new Thread(new Runnable(){
            @Override
            public void run() {
                System.out.println("【数据计算子线程】" + Thread.currentThread().getName() + "开始运行");
                shipCalculate.Calculate();
                System.out.println("【数据计算子线程】运行结束");
            }
        }).start();
    }

    /**
     * 运行计算组件，并在执行完后调用回调函数
     * @param shipCalculate
     */
    public static void RunComputingComponentWithCallBack(ShipCalculate shipCalculate, Object target, String... callBackFunctionName) {
        new Thread(new Runnable(){
            @Override
            public void run() {
                System.out.println("【数据计算子线程】" + Thread.currentThread().getName() + "开始运行");
                shipCalculate.Calculate();
                System.out.println("【数据计算子线程】运行结束");

                try {
                    // 运行回调函数
                    for (String s : callBackFunctionName) {
                        Method callBackFunction = target.getClass().getDeclaredMethod(s);
                        callBackFunction.invoke(target);
                    }
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }

            }
        }).start();
    }

    public static ParamChangeUtil GetCalculateComponentData() {
        return paramChangeUtil;
    }
}
